<!DOCTYPE html>
<html>
<head>
    <title>Speed-Time Graph</title>
</head>
<body>
<canvas id="physicsCanvas" width="550" height="480"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Configuration ---
    const margin = { top: 40, right: 40, bottom: 80, left: 80 };
    const width = canvas.width;
    const height = canvas.height;
    const graphWidth = width - margin.left - margin.right;
    const graphHeight = height - margin.top - margin.bottom;

    const tMax = 40; // max time in s
    const vMax = 20; // max speed in m/s

    // --- Coordinate Transformation Functions ---
    function t_to_x(t) {
        return margin.left + (t / tMax) * graphWidth;
    }

    function v_to_y(v) {
        return height - margin.bottom - (v / vMax) * graphHeight;
    }

    // --- Drawing ---
    ctx.clearRect(0, 0, width, height);
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, width, height);

    // 1. Draw Grid Lines
    ctx.strokeStyle = '#dcdcdc'; // Light grey for all grid lines
    ctx.lineWidth = 1;

    // Vertical grid lines (every 1s)
    for (let t = 1; t <= tMax; t++) {
        ctx.beginPath();
        ctx.moveTo(t_to_x(t), v_to_y(0));
        ctx.lineTo(t_to_x(t), v_to_y(vMax));
        ctx.stroke();
    }

    // Horizontal grid lines (every 0.5 m/s)
    for (let v = 0.5; v <= vMax; v += 0.5) {
        ctx.beginPath();
        ctx.moveTo(t_to_x(0), v_to_y(v));
        ctx.lineTo(t_to_x(tMax), v_to_y(v));
        ctx.stroke();
    }

    // Draw thicker grid lines at major intervals
    ctx.strokeStyle = '#c0c0c0';
    
    // Vertical every 10s
    for (let t = 10; t < tMax; t += 10) {
        ctx.beginPath();
        ctx.moveTo(t_to_x(t), v_to_y(0));
        ctx.lineTo(t_to_x(t), v_to_y(vMax));
        ctx.stroke();
    }
    
    // Horizontal every 5 m/s
    for (let v = 5; v < vMax; v += 5) {
        ctx.beginPath();
        ctx.moveTo(t_to_x(0), v_to_y(v));
        ctx.lineTo(t_to_x(tMax), v_to_y(v));
        ctx.stroke();
    }

    // 2. Draw Axes
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 1.5;

    // X-axis
    ctx.beginPath();
    ctx.moveTo(t_to_x(0), v_to_y(0));
    ctx.lineTo(t_to_x(tMax), v_to_y(0));
    ctx.stroke();

    // Y-axis
    ctx.beginPath();
    ctx.moveTo(t_to_x(0), v_to_y(0));
    ctx.lineTo(t_to_x(0), v_to_y(vMax));
    ctx.stroke();

    // 3. Draw Labels and Ticks
    ctx.fillStyle = 'black';
    ctx.font = '16px sans-serif';

    // X-axis ticks and labels
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';
    for (let t = 0; t <= tMax; t += 10) {
        ctx.fillText(t, t_to_x(t), v_to_y(0) + 8);
    }
    ctx.fillText('time / s', t_to_x(tMax / 2), v_to_y(0) + 35);

    // Y-axis ticks and labels
    ctx.textAlign = 'right';
    ctx.textBaseline = 'middle';
    for (let v = 0; v <= vMax; v += 5) {
        ctx.fillText(v, t_to_x(0) - 10, v_to_y(v));
    }

    // Y-axis title ("speed / m/s")
    const yLabelX = margin.left - 45;
    const yLabelY = margin.top + graphHeight / 2;
    ctx.textAlign = 'center';
    ctx.fillText('speed', yLabelX, yLabelY - 12);
    ctx.fillText('m/s', yLabelX, yLabelY + 12);
    ctx.beginPath();
    ctx.moveTo(yLabelX - 22, yLabelY);
    ctx.lineTo(yLabelX + 22, yLabelY);
    ctx.stroke();

    // 4. Draw the Graph Line
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(t_to_x(0), v_to_y(0));
    
    // Linear part from t=0 to t=20
    ctx.lineTo(t_to_x(20), v_to_y(12));

    // Curved part from t=20 to t=40
    // Based on passing through (30, 17.5) and having tangents 0.6 at start and 0 at end
    // Calculated control points in graph coordinates: P1(26.67, 16), P2(33.33, 20)
    ctx.bezierCurveTo(
        t_to_x(26.67), v_to_y(16),
        t_to_x(33.33), v_to_y(20),
        t_to_x(40), v_to_y(20)
    );
    ctx.stroke();

    // 5. Draw Figure Caption
    ctx.font = 'bold 16px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText('Fig. 1.1', width / 2, height - 20);

</script>
</body>
</html>